/**
 * @ignore
 * Add maximizeWindow/restoreWindow to Editor.
 * @author yiminghe@gmail.com
 */

var Editor = require('editor');
var Event = require('event/dom');
var util = require('util');
var UA = require('ua'),
    ie = UA.ie,
    doc = document,
    $ = require('node'),
    Dom = require('dom'),
    iframe,
    MAXIMIZE_TOOLBAR_CLASS = 'editor-toolbar-padding',
    init = function () {
        if (!iframe) {
            iframe = $('<' + 'iframe ' +
                ' style="' +
                'position:absolute;' +
                'top:-9999px;' +
                'left:-9999px;' +
                '"' +
                ' frameborder="0">').prependTo(doc.body, undefined);
        }
    };

function MaximizeCmd(editor) {
    this.editor = editor;
}

util.augment(MaximizeCmd, {
    restoreWindow: function () {
        var self = this,
            editor = self.editor;

        if (editor.fire('beforeRestoreWindow') === false) {
            return;
        }

        if (self._resize) {
            Event.remove(window, 'resize', self._resize);
            self._resize.stop();
            self._resize = 0;
        } else {
            return;
        }

        //body overflow 变化也会引起 resize 变化！！！！先去除
        self._saveEditorStatus();
        self._restoreState();

        //firefox 必须timeout
        setTimeout(function () {
            self._restoreEditorStatus();
            editor.notifySelectionChange();
            editor.fire('afterRestoreWindow');
        }, 30);
    },

    /*
     从内存恢复最大化前的外围状态信息到编辑器实际动作，
     包括编辑器位置以及周围元素，浏览器窗口
     */
    _restoreState: function () {
        var self = this,
            editor = self.editor,
            textareaEl = editor.get('textarea'),
        //恢复父节点的position原状态 bugfix:最大化被父元素限制
            _savedParents = self._savedParents;
        if (_savedParents) {
            for (var i = 0; i < _savedParents.length; i++) {
                var po = _savedParents[i];
                po.el.css('position', po.position);
            }
            self._savedParents = null;
        }
        //如果没有失去焦点，重新获得当前选取元素
        //self._saveEditorStatus();
        textareaEl.parent().css({
            height: self.iframeHeight
        });
        textareaEl.css({
            height: self.iframeHeight
        });
        Dom.css(doc.body, {
            width: '',
            height: '',
            overflow: ''
        });
        //documentElement 设置宽高，ie崩溃
        doc.documentElement.style.overflow = '';

        var editorElStyle = editor.get('el')[0].style;
        editorElStyle.position = 'static';
        editorElStyle.width = self.editorElWidth;

        iframe.css({
            left: '-99999px',
            top: '-99999px'
        });

        window.scrollTo(self.scrollLeft, self.scrollTop);

        if (ie < 8) {
            editor.get('toolBarEl').removeClass(
                    editor.get('prefixCls') + MAXIMIZE_TOOLBAR_CLASS, undefined);
        }
    },
    /*
     保存最大化前的外围状态信息到内存，
     包括编辑器位置以及周围元素，浏览器窗口
     */
    _saveSate: function () {
        var self = this,
            editor = self.editor,
            _savedParents = [],
            editorEl = editor.get('el');
        self.iframeHeight = editor.get('textarea').parent().style('height');
        self.editorElWidth = editorEl.style('width');
        //主窗口滚动条也要保存哦
        self.scrollLeft = Dom.scrollLeft();
        self.scrollTop = Dom.scrollTop();
        window.scrollTo(0, 0);

        //将父节点的position都改成static并保存原状态 bugfix:最大化被父元素限制
        var p = editorEl.parent();

        while (p) {
            var pre = p.css('position');
            if (pre !== 'static') {
                _savedParents.push({
                    el: p,
                    position: pre
                });
                p.css('position', 'static');
            }
            p = p.parent();
        }
        self._savedParents = _savedParents;

        //ie6,7 图标到了窗口边界，不可点击，给个padding
        if (ie < 8) {
            editor.get('toolBarEl').addClass(
                    editor.get('prefixCls') + MAXIMIZE_TOOLBAR_CLASS, undefined);
        }
    },

    /*
     编辑器自身核心状态保存，每次最大化最小化都要save,restore，
     firefox修正，iframe layout变化时，range丢了
     */
    _saveEditorStatus: function () {
        var self = this,
            editor = self.editor;
        self.savedRanges = null;
        if (!UA.gecko || !editor.__iframeFocus) {
            return;
        }
        var sel = editor.getSelection();
        //firefox 光标丢失bug,位置丢失，所以这里保存下
        self.savedRanges = sel && sel.getRanges();
    },

    /*
     编辑器自身核心状态恢复，每次最大化最小化都要save,restore，
     维持编辑器核心状态不变
     */
    _restoreEditorStatus: function () {
        var self = this,
            editor = self.editor,
            sel = editor.getSelection(),
            savedRanges = self.savedRanges;

        //firefox焦点bug

        //原来是聚焦，现在刷新designmode
        //firefox 先失去焦点才行
        if (UA.gecko) {
            editor.activateGecko();
        }

        if (savedRanges && sel) {
            sel.selectRanges(savedRanges);
        }

        //firefox 有焦点时才重新聚焦
        if (editor.__iframeFocus && sel) {
            var element = sel.getStartElement();
            //使用原生不行的，会使主窗口滚动
            //element[0] && element[0].scrollIntoView(true);
            if (element) {
                element.scrollIntoView(undefined, {
                    alignWithTop: false,
                    allowHorizontalScroll: true,
                    onlyScrollIfNeeded: true
                });
            }
        }
    },

    /*
     将编辑器最大化-实际动作
     必须做两次，何解？？
     */
    _maximize: function (stop) {
        var self = this,
            editor = self.editor,
            editorEl = editor.get('el'),
            viewportHeight = Dom.viewportHeight(),
            viewportWidth = Dom.viewportWidth(),
            textareaEl = editor.get('textarea'),
            statusHeight = editor.get('statusBarEl') ?
                editor.get('statusBarEl')[0].offsetHeight : 0,
            toolHeight = editor.get('toolBarEl')[0].offsetHeight;

        if (!ie) {
            Dom.css(doc.body, {
                width: 0,
                height: 0,
                overflow: 'hidden'
            });
        } else {
            doc.body.style.overflow = 'hidden';
        }
        doc.documentElement.style.overflow = 'hidden';

        editorEl.css({
            position: 'absolute',
            zIndex: Editor.baseZIndex(Editor.ZIndexManager.MAXIMIZE),
            width: viewportWidth + 'px'
        });
        iframe.css({
            zIndex: Editor.baseZIndex(Editor.ZIndexManager.MAXIMIZE - 5),
            height: viewportHeight + 'px',
            width: viewportWidth + 'px'
        });
        editorEl.offset({
            left: 0,
            top: 0
        });
        iframe.css({
            left: 0,
            top: 0
        });

        textareaEl.parent().css({
            height: (viewportHeight - statusHeight - toolHeight ) + 'px'
        });

        textareaEl.css({
            height: (viewportHeight - statusHeight - toolHeight ) + 'px'
        });

        if (stop !== true) {
            /*jshint noarg:false*/
            arguments.callee.call(self, true);
        }
    },
    _real: function () {
        var self = this,
            editor = self.editor;
        if (self._resize) {
            return;
        }

        self._saveEditorStatus();
        self._saveSate();
        self._maximize();
        if (!self._resize) {
            self._resize = util.buffer(function () {
                self._maximize();
                editor.fire('afterMaximizeWindow');
            }, 100);
        }

        Event.on(window, 'resize', self._resize);

        setTimeout(function () {
            self._restoreEditorStatus();
            editor.notifySelectionChange();
            editor.fire('afterMaximizeWindow');
        }, 30);
    },
    maximizeWindow: function () {
        var self = this,
            editor = self.editor;
        if (editor.fire('beforeMaximizeWindow') === false) {
            return;
        }
        init();
        self._real();
    },
    destroy: function () {
        var self = this;
        if (self._resize) {
            Event.remove(window, 'resize', self._resize);
            self._resize.stop();
            self._resize = 0;
        }
    }
});

module.exports = {
    init: function (editor) {
        if (!editor.hasCommand('maximizeWindow')) {
            var maximizeCmd = new MaximizeCmd(editor);

            editor.addCommand('maximizeWindow', {
                exec: function () {
                    maximizeCmd.maximizeWindow();
                }
            });

            editor.addCommand('restoreWindow', {
                exec: function () {
                    maximizeCmd.restoreWindow();
                }
            });
        }
    }
};